"""
PySide6 柱状图组件
完整的柱状图实现，包含数据编辑和自定义功能
"""

import sys
import random
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QPushButton, QTableWidget, QTableWidgetItem, QHeaderView,
    QGroupBox, QFormLayout, QInputDialog, QMessageBox, 
    QTabWidget, QSplitter, QFileDialog
)
from PySide6.QtCharts import (
    QChart, QChartView, QBarSeries, QBarSet, QBarCategoryAxis, QValueAxis
)
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QPainter, QColor


class BarChartWidget(QWidget):
    """柱状图组件"""
    
    dataChanged = Signal()  # 数据变化信号
    
    def __init__(self):
        super().__init__()
        self.chart = None
        self.chart_view = None
        self.series = None
        self.categories = []
        self.data_sets = []
        self.init_ui()
        self.setup_chart()
        
    def init_ui(self):
        """初始化界面"""
        layout = QVBoxLayout(self)
        
        # 创建图表视图
        self.chart_view = QChartView()
        self.chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)
        
        layout.addWidget(self.chart_view)
        
    def setup_chart(self):
        """设置图表"""
        # 创建柱状图系列
        self.series = QBarSeries()
        
        # 创建图表
        self.chart = QChart()
        self.chart.addSeries(self.series)
        self.chart.setTitle("柱状图")
        self.chart.setAnimationOptions(QChart.AnimationOption.SeriesAnimations)
        
        # 设置图表视图
        self.chart_view.setChart(self.chart)
        
    def set_data(self, categories, data_sets):
        """
        设置图表数据
        :param categories: 分类列表
        :param data_sets: 数据集列表，每个元素为 (标签, 颜色, 数据列表) 的元组
        """
        self.categories = categories
        self.data_sets = data_sets
        
        # 清除现有系列
        if self.series:
            self.chart.removeSeries(self.series)
        
        # 创建新的柱状图系列
        self.series = QBarSeries()
        
        # 添加数据集
        for label, color, data in data_sets:
            bar_set = QBarSet(label)
            if isinstance(color, str):
                bar_set.setColor(QColor(color))
            else:
                bar_set.setColor(color)
            
            for value in data:
                bar_set.append(value)
                
            self.series.append(bar_set)
            
        # 添加系列到图表
        self.chart.addSeries(self.series)
        
        # 创建坐标轴
        self.create_axes()
        
    def create_axes(self):
        """创建坐标轴"""
        # 清除现有坐标轴
        for axis in self.chart.axes():
            self.chart.removeAxis(axis)
        
        # 分类轴（X轴）
        self.axis_x = QBarCategoryAxis()
        self.axis_x.append(self.categories)
        self.axis_x.setTitleText("分类")
        self.chart.addAxis(self.axis_x, Qt.AlignmentFlag.AlignBottom)
        self.series.attachAxis(self.axis_x)
        
        # 数值轴（Y轴）
        self.axis_y = QValueAxis()
        self.axis_y.setTitleText("数值")
        self.axis_y.setLabelFormat("%.1f")
        
        # 自动调整Y轴范围
        if self.data_sets:
            all_values = []
            for _, _, data in self.data_sets:
                all_values.extend(data)
            if all_values:
                max_value = max(all_values)
                min_value = min(all_values)
                if max_value != min_value:
                    range_value = max_value - min_value
                    self.axis_y.setRange(min_value - range_value * 0.1, max_value + range_value * 0.1)
                else:
                    self.axis_y.setRange(min_value * 0.9, max_value * 1.1)
        
        self.chart.addAxis(self.axis_y, Qt.AlignmentFlag.AlignLeft)
        self.series.attachAxis(self.axis_y)
        
    def update_chart_title(self, title):
        """更新图表标题"""
        self.chart.setTitle(title)
        
    def update_axis_titles(self, x_title, y_title):
        """更新坐标轴标题"""
        self.axis_x.setTitleText(x_title)
        self.axis_y.setTitleText(y_title)


class DataEditorWidget(QWidget):
    """数据编辑器组件"""
    
    dataModified = Signal(list, list)  # 数据修改信号 (categories, data_sets)
    
    def __init__(self):
        super().__init__()
        self.categories = []
        self.data_sets = []
        self.table = None
        self.init_ui()
        
    def init_ui(self):
        """初始化界面"""
        layout = QVBoxLayout(self)
        
        # 创建工具栏
        toolbar = QHBoxLayout()
        
        self.add_category_btn = QPushButton("添加分类")
        self.add_category_btn.clicked.connect(self.add_category)
        toolbar.addWidget(self.add_category_btn)
        
        self.add_dataset_btn = QPushButton("添加数据集")
        self.add_dataset_btn.clicked.connect(self.add_data_set)
        toolbar.addWidget(self.add_dataset_btn)
        
        self.clear_btn = QPushButton("清空数据")
        self.clear_btn.clicked.connect(self.clear_data)
        toolbar.addWidget(self.clear_btn)
        
        toolbar.addStretch()
        
        # 创建数据表格
        self.table = QTableWidget(1, 1)
        self.table.setHorizontalHeaderLabels(["分类"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        
        # 连接信号
        self.table.cellChanged.connect(self.on_cell_changed)
        
        layout.addLayout(toolbar)
        layout.addWidget(self.table)
        
    def set_data(self, categories, data_sets):
        """设置数据"""
        self.categories = categories.copy()
        self.data_sets = [list(ds) for ds in data_sets]  # 深拷贝
        
        self.update_table()
        
    def update_table(self):
        """更新表格显示"""
        # 清空表格
        self.table.clear()
        
        # 设置列数（分类列 + 数据集列）
        column_count = 1 + len(self.data_sets)
        self.table.setColumnCount(column_count)
        
        # 设置表头
        headers = ["分类"]
        for data_set in self.data_sets:
            headers.append(data_set[0])  # 数据集标签
        self.table.setHorizontalHeaderLabels(headers)
        
        # 设置行数
        row_count = max(len(self.categories), 1)
        self.table.setRowCount(row_count)
        
        # 填充数据
        for row in range(row_count):
            # 分类列
            category = self.categories[row] if row < len(self.categories) else ""
            item = QTableWidgetItem(category)
            self.table.setItem(row, 0, item)
            
            # 数据列
            for col, data_set in enumerate(self.data_sets):
                value = data_set[2][row] if row < len(data_set[2]) else 0
                item = QTableWidgetItem(str(value))
                self.table.setItem(row, col + 1, item)
                
    def on_cell_changed(self, row, column):
        """单元格内容变化处理"""
        if column == 0:
            # 分类名称变化
            item = self.table.item(row, column)
            if item:
                # 扩展分类列表
                while len(self.categories) <= row:
                    self.categories.append("")
                self.categories[row] = item.text()
        else:
            # 数据值变化
            item = self.table.item(row, column)
            if item:
                try:
                    value = float(item.text())
                    data_set_index = column - 1
                    if data_set_index < len(self.data_sets):
                        # 扩展数据列表
                        while len(self.data_sets[data_set_index][2]) <= row:
                            self.data_sets[data_set_index][2].append(0)
                        self.data_sets[data_set_index][2][row] = value
                except ValueError:
                    pass  # 输入非数字，忽略
        
        # 发出数据修改信号
        self.dataModified.emit(self.categories, self.data_sets)
        
    def add_category(self):
        """添加分类"""
        category_name, ok = QInputDialog.getText(self, "添加分类", "分类名称:")
        if ok and category_name:
            self.categories.append(category_name)
            self.update_table()
            self.dataModified.emit(self.categories, self.data_sets)
            
    def add_data_set(self):
        """添加数据集"""
        label, ok = QInputDialog.getText(self, "添加数据集", "数据集名称:")
        if ok and label:
            # 生成随机颜色
            color = QColor(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
            
            # 创建数据列表（与分类数量一致）
            data = [0] * len(self.categories)
            
            self.data_sets.append([label, color, data])
            self.update_table()
            self.dataModified.emit(self.categories, self.data_sets)
            
    def clear_data(self):
        """清空数据"""
        reply = QMessageBox.question(self, "确认", "确定要清空所有数据吗？", 
                                   QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        if reply == QMessageBox.StandardButton.Yes:
            self.categories.clear()
            self.data_sets.clear()
            self.update_table()
            self.dataModified.emit(self.categories, self.data_sets)


class ChartControlPanel(QWidget):
    """图表控制面板"""
    
    def __init__(self, chart_widget, data_editor):
        super().__init__()
        self.chart_widget = chart_widget
        self.data_editor = data_editor
        self.init_ui()
        
    def init_ui(self):
        """初始化控制面板界面"""
        layout = QVBoxLayout(self)
        
        # 图表标题设置
        title_group = QGroupBox("图表设置")
        title_layout = QFormLayout(title_group)
        
        self.title_input = QPushButton("柱状图")
        self.title_input.clicked.connect(self.change_title)
        title_layout.addRow("标题:", self.title_input)
        
        # 坐标轴设置
        axis_group = QGroupBox("坐标轴设置")
        axis_layout = QFormLayout(axis_group)
        
        self.x_axis_input = QPushButton("分类")
        self.x_axis_input.clicked.connect(self.change_x_axis_title)
        axis_layout.addRow("X轴标题:", self.x_axis_input)
        
        self.y_axis_input = QPushButton("数值")
        self.y_axis_input.clicked.connect(self.change_y_axis_title)
        axis_layout.addRow("Y轴标题:", self.y_axis_input)
        
        # 数据操作
        data_group = QGroupBox("数据操作")
        data_layout = QVBoxLayout(data_group)
        
        self.sample_data_btn = QPushButton("加载示例数据")
        self.sample_data_btn.clicked.connect(self.load_sample_data)
        data_layout.addWidget(self.sample_data_btn)
        
        self.random_data_btn = QPushButton("生成随机数据")
        self.random_data_btn.clicked.connect(self.generate_random_data)
        data_layout.addWidget(self.random_data_btn)
        
        # 添加到主布局
        layout.addWidget(title_group)
        layout.addWidget(axis_group)
        layout.addWidget(data_group)
        layout.addStretch()
        
    def change_title(self):
        """更改图表标题"""
        current_title = self.chart_widget.chart.title()
        title, ok = QInputDialog.getText(self, "更改标题", "新标题:", text=current_title)
        if ok and title:
            self.chart_widget.update_chart_title(title)
            self.title_input.setText(title)
        
    def change_x_axis_title(self):
        """更改X轴标题"""
        current_title = self.chart_widget.axis_x.titleText()
        title, ok = QInputDialog.getText(self, "更改X轴标题", "新标题:", text=current_title)
        if ok and title:
            self.chart_widget.update_axis_titles(title, self.chart_widget.axis_y.titleText())
            self.x_axis_input.setText(title)
        
    def change_y_axis_title(self):
        """更改Y轴标题"""
        current_title = self.chart_widget.axis_y.titleText()
        title, ok = QInputDialog.getText(self, "更改Y轴标题", "新标题:", text=current_title)
        if ok and title:
            self.chart_widget.update_axis_titles(self.chart_widget.axis_x.titleText(), title)
            self.y_axis_input.setText(title)
        
    def load_sample_data(self):
        """加载示例数据"""
        categories = ["产品A", "产品B", "产品C", "产品D", "产品E"]
        data_sets = [
            ("销量", "#FF6B6B", [120, 150, 180, 200, 170]),
            ("库存", "#4ECDC4", [80, 100, 120, 90, 110]),
            ("利润", "#45B7D1", [40, 50, 60, 70, 60])
        ]
        self.chart_widget.set_data(categories, data_sets)
        self.data_editor.set_data(categories, data_sets)
        
    def generate_random_data(self):
        """生成随机数据"""
        categories = [f"分类{i+1}" for i in range(5)]
        data_sets = [
            ("数据集1", "#FF6B6B", [random.randint(50, 200) for _ in range(5)]),
            ("数据集2", "#4ECDC4", [random.randint(30, 150) for _ in range(5)]),
            ("数据集3", "#45B7D1", [random.randint(20, 100) for _ in range(5)])
        ]
        self.chart_widget.set_data(categories, data_sets)
        self.data_editor.set_data(categories, data_sets)


class MainWindow(QMainWindow):
    """主窗口"""
    
    def __init__(self):
        super().__init__()
        self.init_ui()
        
    def init_ui(self):
        """初始化主窗口界面"""
        self.setWindowTitle("PySide6 柱状图工具")
        self.setGeometry(100, 100, 1000, 700)
        
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 创建标签页
        tab_widget = QTabWidget()
        
        # 创建柱状图组件
        self.chart_widget = BarChartWidget()
        
        # 创建数据编辑器
        self.data_editor = DataEditorWidget()
        
        # 连接信号
        self.data_editor.dataModified.connect(self.on_data_modified)
        
        # 添加到标签页
        tab_widget.addTab(self.chart_widget, "图表显示")
        tab_widget.addTab(self.data_editor, "数据编辑")
        
        # 创建控制面板
        self.control_panel = ChartControlPanel(self.chart_widget, self.data_editor)
        
        # 创建分割器
        splitter = QSplitter(Qt.Orientation.Horizontal)
        splitter.addWidget(tab_widget)
        splitter.addWidget(self.control_panel)
        splitter.setSizes([700, 300])
        
        main_layout.addWidget(splitter)
        
        # 添加一些示例数据
        self.load_sample_data()
        
    def on_data_modified(self, categories, data_sets):
        """数据修改处理"""
        self.chart_widget.set_data(categories, data_sets)
        
    def load_sample_data(self):
        """加载示例数据"""
        self.control_panel.load_sample_data()


def main():
    """主函数"""
    app = QApplication(sys.argv)
    
    # 创建并显示主窗口
    window = MainWindow()
    window.show()
    
    sys.exit(app.exec())


if __name__ == "__main__":
    main()